package com.wuwei.elearning.question.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wuwei.elearning.exception.ElearningMysqlException;
import com.wuwei.elearning.question.domain.*;
import com.wuwei.elearning.question.mapper.*;
import com.wuwei.elearning.question.service.SettingQuestionsService;
import com.wuwei.elearning.utils.word.WordUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.*;
import org.jetbrains.annotations.NotNull;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SettingQuestionsServiceImpl implements SettingQuestionsService {

    @Resource
    private QuestionSettingForDa42SupMapper questionSettingForDa42SupMapper;

    @Resource
    private QuestionMapper questionMapper;


    @Resource
    private QuestionSettingForDa42Mapper questionSettingForDa42Mapper;
    @Autowired
    private SubjectMapper subjectMapper;


    @Override
    public void setQuestions(String engine, String ata22Type,Integer type)  {
        /*
        1.先拿到Da42考卷各子章节需要出多少道题，放到一个arrayList中
        2.再拿到Da42所有的考题
        3.根据Da42各子章节需求出题的数量出题，出完再放到一个考卷arrayList中
        4.将考卷arrayList中的题目写到一个docx文件中
        5.将写好的docx文件地址返回给controller层，由controller层返回给前端
         */
        if (type == 1) {
            //纯中文的题目
            setQuestionZhCn(engine,ata22Type);
        } else if (type == 0) {
            //英文的题目
            setQuestionsEn(engine,ata22Type);
        }
    }

    @Resource
    private QuestionTranslatedMapper questionTranslatedMapper;

    private void setQuestionsEn(String engine, String ata22Type) {
        //获取question
//        List<Question> questions = this.getQuestions(engine,ata22Type);
        //改成带有特殊注意点的题目
        List<Question> questions = getQuestionsWithSpecialCares(engine, ata22Type);
        List<QuestionTranslated> questionTranslateds = questions.stream().map(q -> {
            Long id = q.getId();
            QuestionTranslated questionTranslated = questionTranslatedMapper.selectOne(new LambdaQueryWrapper<QuestionTranslated>().eq(QuestionTranslated::getQuestionId, id));
            if (questionTranslated == null) {
                throw new ElearningMysqlException(30055, "题目生成失败，id为" + id + "的题目在questionTranslate表中没有与之对应的翻译版本！");
            }
            return questionTranslated;
        }).collect(Collectors.toList());
        wordUtils.writeToBeDocxForTable(questionTranslateds);
    }

    @Resource
    private WordUtils wordUtils;

    @Resource
    private SpecialCareMapper specialCareMapper;

    /**
     * 获取带有特别关注点的机型题目
     * 1 根据科目id随机获取所有机型题目，某一个科目需要获取的题目数量为该科目的时长除以60的向上取整
     * 2 优先获取特别关注点的题目
     * 3 某一科目的特别关注点的数量不能超过该科目应该获取的总的题目数量
     * 4 特别关注点的题目获取完了以后，如果还要获取题目，则获取普通题目
     * @return
     */
    private List<Question> getQuestionsWithSpecialCares(String engine, String ata22Type){
        List<Subject> subjects = subjectMapper.getLeafsById(7L);
        subjects = filterSubjects(engine, ata22Type, subjects);
        List<Question> questions = new ArrayList<>();
        // question表中的subjectId就是subject的主键，因此可以根据subjects的id去question表中查数据
        for (Subject subject : subjects) {
            Long id = subject.getId();
            Integer duration = subject.getDuration();
            Integer count = (int) Math.ceil((double) duration /60);
            //先去查询该subject有几个特别关注点，一个特别关注点只出一道题
            List<SpecialCare> specialCares = specialCareMapper.selectList(new LambdaQueryWrapper<SpecialCare>().eq(SpecialCare::getSubjectId, subject.getId()));
            ArrayList<Long> qid = new ArrayList<>();
            if (!specialCares.isEmpty()) {
                if (specialCares.size()>count) {
                    throw new ElearningMysqlException(30055, "题目生成失败，id为" + id + "的题目特别关注点数量大于题目数量！");
                }
                List<Question> specialQuestions = new ArrayList<>();
                for (SpecialCare specialCare : specialCares) {
                    Integer specialCareId = specialCare.getId();
                    //根据特别关注点id和subjectId去question表中查数据，这里随机查找一条数据
                    List<Question> q = questionMapper.randomSelectBySpecialCareId(id,specialCareId, 1);
                    specialQuestions.addAll(q);
                }
                qid = specialQuestions.stream().map(Question::getId).collect(Collectors.toCollection(ArrayList::new));
                questions.addAll(specialQuestions);
            }
            //特别关注点的题目查找完了以后，再去查找剩余的题目,这里再去查找的时候不能和之前的题目重复
            List<Question> questionList = new ArrayList<>();
            if (qid.isEmpty()) {
                questionList = questionMapper.randomSelect(id,count-specialCares.size());
            } else {
                questionList = questionMapper.randomSelectWithoutInQid(id,count-specialCares.size(),qid);
            }

            if (questionList.size()!=count-specialCares.size()) {
                throw new ElearningMysqlException(30055, "题目生成失败，id为" + id + "题库内题目数量不足以支撑生成题库！");
            }
            questions.addAll(questionList);
        }
        return questions;
    }

    private List<Question> getQuestions(String engine, String ata22Type) {
        List<Subject> subjects = subjectMapper.getLeafsById(7L);

        subjects = filterSubjects(engine, ata22Type, subjects);

        List<Question> questions = new ArrayList<>();
        // question表中的subjectId就是subject的主键，因此可以根据subjects的id去question表中查数据
        for (Subject subject : subjects) {
            Long id = subject.getId();
            Integer duration = subject.getDuration();
            Integer count = (int) Math.ceil((double) duration /60);
            //随机获取count数量的题目
            List<Question> questionList = questionMapper.randomSelect(id,count);
            questions.addAll(questionList);
        }
        return questions;
    }

    @NotNull
    private static List<Subject> filterSubjects(String engine, String ata22Type, List<Subject> subjects) {
        if (engine.equals("E4")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("TAE")).collect(Collectors.toList());
        } else if (engine.equals("TAE")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("E4")).collect(Collectors.toList());
        } else {
            throw new ElearningMysqlException(20001,"发动机类型必须是E4或TAE！");
        }

        if (ata22Type.equals("GFC700")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("KAP140")).collect(Collectors.toList());
        } else if (ata22Type.equals("KAP140")) {
            subjects = subjects.stream().filter(s -> !s.getName().contains("GFC700")).collect(Collectors.toList());
        } else {
            throw new ElearningMysqlException(20001,"航电系统类型必须是KAP140或GFC700！");
        }
        return subjects;
    }


    /**
     * 纯中文的题目
     * @param engine
     * @param ata22Type
     */
    private void setQuestionZhCn(String engine, String ata22Type) {
//        List<Question> questions = getQuestions(engine, ata22Type);
        List<Question> questions = getQuestionsWithSpecialCares(engine, ata22Type);
        this.setToWord(questions);
        //1.先拿到Da42考卷各子章节需要出多少道题，放到一个arrayList中
//        LambdaQueryWrapper<QuestionSettingForDa42> queryWrapper = new LambdaQueryWrapper<>();
//        if (engine.equals("E4")) {
//            queryWrapper.eq(QuestionSettingForDa42::getType,1);
//            testType = "Austro E4";
//        } else if (engine.equals("TAE")) {
//            queryWrapper.eq(QuestionSettingForDa42::getType,0);
//            testType = "Technify  TAE  125";
//        } else {
//            throw new ElearningMysqlException(20001,"发动机类型必须是E4或TAE！");
//        }
//        List<QuestionSettingForDa42> da42SettingList = questionSettingForDa42Mapper.selectList(queryWrapper);
//
//        Long da42Id = subjectMapper.getIdByName("DA42机型全程班");
        //2.再拿到Da42对应子章节的考题
//        LambdaQueryWrapper<Question> queryWrapper1 = new LambdaQueryWrapper<>();
//        queryWrapper1.eq(Question::getSubjectId,da42Id);
//        List<Question> questionsList = questionMapper.selectList(queryWrapper1);
//
//        List<Question> setQuestionList = new ArrayList<>();
//        da42SettingList.forEach(a->{
//            String ataSubchapter = a.getAtaSubchapter();
//            Integer questionsNum = a.getQuestionsNum();
//            //2.1根据发动机类型把这个类型的发动机的题
//            Question[] questions = questionsList.stream().filter(q -> {
//                String chapter = q.getChapter();
//                String substring = chapter.substring(0, 2);
//                String lastChar = substring.substring(1, 2);
//                String firstChar = substring.substring(0, 1);
//                int chapterIndex = 0;
//                if ("-".equals(lastChar)) {
//                    chapterIndex = Integer.parseInt(firstChar);
//                } else {
//                    chapterIndex = Integer.parseInt(substring);
//                }
//                //如果ATA章节号小于61
//                if (chapterIndex < 61) {
//                    return ataSubchapter.equals(q.getSubChapter());
//                } else {
//
//                    return ((ataSubchapter.equals(q.getSubChapter())) && (chapter.contains(engine)));
//                }
//            }).filter(q -> {
//                //2.2根据ata22的类型将不属于该系统的题去除掉
//                String chapter = q.getChapter();
//                String subChapter = q.getSubChapter();
//                String substring = chapter.substring(0, 2);
//                String lastChar = substring.substring(1, 2);
//                String firstChar = substring.substring(0, 1);
//                int chapterIndex = 0;
//                if ("-".equals(lastChar)) {
//                    chapterIndex = Integer.parseInt(firstChar);
//                } else {
//                    chapterIndex = Integer.parseInt(substring);
//                }
//                if (chapterIndex == 22) {
//                    return subChapter.contains(ata22Type);
//                }
//                return true;
//            }).toArray(Question[]::new);
//            int length = questions.length;
//
//            if (length != 0) {
//                Random random = new Random();
//                Set<Integer> set = new HashSet<>();
//                while (set.size() < questionsNum) {
//                    int index = random.nextInt(length);
//                    if (!set.contains(index)) {
//                        set.add(index);
//                    }
//                }
//                for (int num : set) {
//                    Question questionForDa42 = questions[num];
////                    //将出好的题放到一个新的arrayList中
//                    setQuestionList.add(questionForDa42);
//                }
//            }
//        });
//        questionToWord.writeToBeDocxForTable(setQuestionList,testType);
    }

    /**
     * 取消表格的边框
     * @param table
     */
    private void setTableBorders(XWPFTable table) {
        // 设置表格的边框为0，即隐藏所有边框
        CTTblBorders tblBorders = table.getCTTbl().getTblPr().addNewTblBorders();
        tblBorders.addNewBottom().setVal(STBorder.NONE);
        tblBorders.addNewTop().setVal(STBorder.NONE);
        tblBorders.addNewLeft().setVal(STBorder.NONE);
        tblBorders.addNewRight().setVal(STBorder.NONE);
        tblBorders.addNewInsideH().setVal(STBorder.NONE);
        tblBorders.addNewInsideV().setVal(STBorder.NONE);
    }

    /**
     * 将questions写入word
     * @param setQuestionList
     */
    private void setToWord(List<Question> setQuestionList) {
        String templatePath = "template.docx";
        String wordPath = "word.docx";
        try {
            File file = new File(templatePath);
            if (!file.exists()) {
                throw new ElearningMysqlException(30011, "请检查模板文件是否存在！");
            }
            InputStream is = Files.newInputStream(Paths.get(templatePath));
            XWPFDocument document = new XWPFDocument(is);

            //设置考卷信息
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            XWPFParagraph paragraph = paragraphs.get(1);
            paragraph.getRuns().get(0).setBold(true);

            XWPFTable table = document.createTable(1, 2);
            table.setWidth("100%");
            // Set column widths (each column 50%)
            CTTblLayoutType tblLayout = table.getCTTbl().getTblPr().addNewTblLayout();
            tblLayout.setType(STTblLayoutType.FIXED);
            setTableBorders(table);

            for (int col = 0; col < 2; col++) {
                CTTblGridCol tblCol = table.getCTTbl().addNewTblGrid().addNewGridCol();
                tblCol.setW(BigInteger.valueOf(5000)); // Adjust the width as necessary
            }

            //插入第一道题目
            Question question0 = setQuestionList.get(0);
            XWPFTableCell cell0 = table.getRow(0).getCell(0);
            cell0.setText("1." +question0.getQuestion());
            mergeCellsHorizontally(table,0,0,1);
            int rowNum = 1;
            rowNum = setInnerQuestion(question0, table, rowNum);
            table.createRow();
            rowNum++;
            int questionNum = 2;

            //插入后面的题目
            for (int i = 1; i < setQuestionList.size(); i++) {
                Question question = setQuestionList.get(i);
                XWPFTableRow row = table.createRow();
                rowNum++;
                row.getCell(0).setText(questionNum + "." + question.getQuestion());
                mergeCellsHorizontally(table,rowNum-1,0,1);
                questionNum++;
                rowNum = setInnerQuestion( question, table, rowNum);
                table.createRow();
                rowNum++;
            }

            //设置答案
            setAnswer(document,setQuestionList);
            //Save the document
            FileOutputStream outputStream1 = new FileOutputStream(wordPath);
            document.write(outputStream1);
            outputStream1.close();
            document.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置答案
     * @param document
     * @param setQuestionList
     */
    private void setAnswer(XWPFDocument document, List<Question> setQuestionList) {
        document.createParagraph().createRun().setText("\n");

        String text =  "----------------------------------------------------------后面的为答案----------------------------------------------------------";
        document.createParagraph().createRun().setText(text);

        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < setQuestionList.size(); i++) {
            Question question = setQuestionList.get(i);
            String answer = question.getAnswer();
            builder.append(i+1+"."+answer+"   ");
        }
        document.createParagraph().createRun().setText(builder.toString());
    }

    private int setInnerQuestion( Question question, XWPFTable table, int rowNum) {
        //如果答案比较长，则答案表格变成4行
        if (question.getItem1().length()>12|| question.getItem2().length()>12|| question.getItem3().length()>12|| question.getItem4().length()>12
        ) {
            XWPFTableRow row1 = table.createRow();
            XWPFTableRow row2 = table.createRow();
            XWPFTableRow row3 = table.createRow();
            XWPFTableRow row4 = table.createRow();
            rowNum +=4;
            row1.getCell(0).setText("A."+ question.getItem1());
            row2.getCell(0).setText("B."+ question.getItem2());
            row3.getCell(0).setText("C."+ question.getItem3());
            row4.getCell(0).setText("D."+ question.getItem4());

            mergeCellsHorizontally(table, rowNum -1,0,1);
            mergeCellsHorizontally(table, rowNum -2,0,1);
            mergeCellsHorizontally(table, rowNum -3,0,1);
            mergeCellsHorizontally(table, rowNum -4,0,1);
        }
//                否则答案表格变成2行
        else {
            XWPFTableRow row1 = table.createRow();
            XWPFTableRow row2 = table.createRow();
            rowNum +=2;
            row1.getCell(0).setText("A."+ question.getItem1());
            row1.getCell(1).setText("B."+ question.getItem2());
            row2.getCell(0).setText("C."+ question.getItem3());
            row2.getCell(1).setText("D."+ question.getItem4());

        }
        return rowNum;
    }


    // 方法用于水平合并单元格
    public void mergeCellsHorizontally(XWPFTable table, int row, int fromCol, int toCol) {
        for (int colIndex = fromCol; colIndex <= toCol; colIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(colIndex);
            if ( colIndex == fromCol ) {
                // The first merged cell is set with RESTART merge value
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                // Cells which join (merge) the first one, are set with CONTINUE
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }


    /**
     * TAE补E4的题库
     */
    @Override
    public void settingDa42Sup() {
        /**
         *
         *    List<Subject> subjects = subjectMapper.getLeafsById(subjectId);
         *         if (engine.equals("E4")) {
         *             subjects = subjects.stream().filter(s -> !s.getName().contains("TAE")).collect(Collectors.toList());
         *         } else if (engine.equals("TAE")) {
         *             subjects = subjects.stream().filter(s -> !s.getName().contains("E4")).collect(Collectors.toList());
         *         } else {
         *             throw new ElearningMysqlException(20001,"发动机类型必须是E4或TAE！");
         *         }
         *
         *         if (ata22Type.equals("GFC700")) {
         *             subjects  = subjects.stream().filter(s -> !s.getName().contains("KAP140")).collect(Collectors.toList());
         *         } else if (ata22Type.equals("KAP140")) {
         *             subjects  = subjects.stream().filter(s -> !s.getName().contains("GFC700")).collect(Collectors.toList());
         *         } else {
         *             throw new ElearningMysqlException(20001,"航电系统类型必须是KAP140或GFC700！");
         *         }
         *
         *         List<Question> questions = new ArrayList<>();
         *         // question表中的subjectId就是subject的主键，因此可以根据subjects的id去question表中查数据
         *         for (Subject subject : subjects) {
         *             Long id = subject.getId();
         *             Integer duration = subject.getDuration();
         *             Integer count = (int) Math.ceil((double) duration /60);
         *             //随机获取count数量的题目
         *             List<Question> questionList = questionMapper.randomSelect(subjectId,count);
         *             questions.addAll(questionList);
         *         }
         *         this.setToWord(questions);
         */
        List<Subject> subjects = subjectMapper.getLeafsById(8L);
        List<Question> questions = new ArrayList<>();
        for (Subject subject : subjects) {
            Long id = subject.getId();
            Integer duration = subject.getDuration();
            Integer count = (int) Math.ceil((double) duration /60);
            List<Question> questionList = questionMapper.randomSelect(id,count);
            questions.addAll(questionList);
        }
        this.setToWord(questions);

//        String testType = "Austro E4";
//        //构造一个返回参数的数组
//        List<Question> setQuestionList = new ArrayList<>();
//        //获取所有题目需要出几道题
//        LambdaQueryWrapper<QuestionSettingForDa42Sup> qw = new LambdaQueryWrapper<>();
//        List<QuestionSettingForDa42Sup> list = questionSettingForDa42SupMapper.selectList(qw);
//        //获取所有题目
//        LambdaQueryWrapper<Question> qw1 = new LambdaQueryWrapper<>();
//        qw1.eq(Question::getSubject,"DA42机型TEA补AE班");
//        List<Question> questionList = questionMapper.selectList(qw1);
//        //遍历所有题目设置
//
//        for (int i = 0; i < list.size(); i++) {
//            QuestionSettingForDa42Sup a = list.get(i);
//            String  ataChapter = a.getAtaChapter().toString();
//            //根据ata章节号查询能设置的题目
//            List<Question> collect = questionList.stream()
//                    .filter(question -> question.getChapter().equals(ataChapter))
//                    .collect(Collectors.toList());
//            //随机出题，length是一共有多少道题，从length中抽取questionsNum数量的数，要求不能重复
//            //利用set去重的性质，进行随机出题，保证出到的题目没有重复的
//            int length = collect.size();
//            if (length>0) {
//                Integer questionsNum = a.getQuestionNum();
//                //拿到题目根据questionNum抽取questionNum数量的题目
//                Random random = new Random();
//                Set<Integer> set = new HashSet<>();
//                while (set.size() < questionsNum) {
//                    int index = random.nextInt(length);
//                    set.add(index);
//                }
//                for (int num : set) {
//                    Question questionForDa42Sup = collect.get(num);
////                    //将出好的题放到一个新的arrayList中
//                    setQuestionList.add(questionForDa42Sup);
//                }
//            }
//        }
//
//        questionToWord.writeToBeDocxForTable(setQuestionList,testType);
    }
}
